package com.ruoyi.media.mpQrcode.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.HexUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dtflys.forest.utils.Base64Utils;
import com.gargoylesoftware.htmlunit.webstart.WebStartHandler;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.media.forestApi.DouyinApi;
import com.ruoyi.media.mpQrcode.domain.MediaMpQrcodeLink;
import com.ruoyi.media.mpQrcode.domain.bo.MediaMpQrcodeLinkBo;
import com.ruoyi.media.mpQrcode.domain.vo.MediaMpQrcodeLinkVo;
import com.ruoyi.media.mpQrcode.mapper.MediaMpQrcodeLinkMapper;
import com.ruoyi.media.mpQrcode.service.IMediaMpQrcodeLinkService;
import com.ruoyi.media.mpQrcodeData.domain.MediaMpQrcodeData;
import com.ruoyi.media.mpQrcodeData.domain.bo.MediaMpQrcodeDataBo;
import com.ruoyi.media.mpQrcodeData.mapper.MediaMpQrcodeDataMapper;
import com.ruoyi.media.mpQrcodeData.service.IMediaMpQrcodeDataService;
import com.ruoyi.media.utils.WxUtils;
import com.ruoyi.media.utils.XStringUtils;
import com.yzk18.commons.QRCodeHelpers;
import lombok.RequiredArgsConstructor;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.springframework.stereotype.Service;
//import sun.misc.BASE64Decoder;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 微信群二维码参数Service业务层处理
 *
 * @author dqw
 * @date 2023-04-24
 */
@RequiredArgsConstructor
@Service
public class MediaMpQrcodeLinkServiceImpl extends ServiceImpl<MediaMpQrcodeLinkMapper,MediaMpQrcodeLink> implements IMediaMpQrcodeLinkService {

    private final MediaMpQrcodeLinkMapper baseMapper;

    private final MediaMpQrcodeDataMapper mediaMpQrcodeDataMapper;

    private final DouyinApi douyinApi;

    private final IMediaMpQrcodeDataService mediaMpQrcodeDataService;

    /**
     * 查询微信群二维码参数
     */
    @Override
    public MediaMpQrcodeLinkVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询微信群二维码参数列表
     */
    @Override
    public TableDataInfo<MediaMpQrcodeLinkVo> queryPageList(MediaMpQrcodeLinkBo bo, PageQuery pageQuery) {
        LoginUser loginUser =  LoginHelper.getLoginUser();
        if(loginUser == null){
            throw new RuntimeException("当前用户登录凭据异常！");
        }
        //bo.setCreateBy(loginUser.getUsername());
        LambdaQueryWrapper<MediaMpQrcodeLink> lqw = buildQueryWrapper(bo);
        Page<MediaMpQrcodeLinkVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        List<MediaMpQrcodeLinkVo> mediaMpQrcodeLinkVoList = result.getRecords();
        for(MediaMpQrcodeLinkVo item : mediaMpQrcodeLinkVoList){
            item.setLinkNum(mediaMpQrcodeDataMapper.getDataCount(String.valueOf(item.getId())));
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询微信群二维码参数列表
     */
    @Override
    public List<MediaMpQrcodeLinkVo> queryList(MediaMpQrcodeLinkBo bo) {
        LambdaQueryWrapper<MediaMpQrcodeLink> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<MediaMpQrcodeLink> buildQueryWrapper(MediaMpQrcodeLinkBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<MediaMpQrcodeLink> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getDeptId() != null, MediaMpQrcodeLink::getDeptId, bo.getDeptId());
        lqw.eq(bo.getUserId() != null, MediaMpQrcodeLink::getUserId, bo.getUserId());
        lqw.eq(bo.getCreateBy() != null, MediaMpQrcodeLink::getCreateBy, bo.getCreateBy());
        lqw.eq(StringUtils.isNotBlank(bo.getLink()), MediaMpQrcodeLink::getLink, bo.getLink());
        lqw.eq(StringUtils.isNotBlank(bo.getQrCodeData()), MediaMpQrcodeLink::getQrCodeData, bo.getQrCodeData());
        lqw.eq(StringUtils.isNotBlank(bo.getAccount()), MediaMpQrcodeLink::getAccount, bo.getAccount());
        return lqw;
    }

    /**
     * 新增微信群二维码参数
     */
    @Override
    public Boolean insertByBo(MediaMpQrcodeLinkBo bo) {
        MediaMpQrcodeLink add = BeanUtil.toBean(bo, MediaMpQrcodeLink.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改微信群二维码参数
     */
    @Override
    public Boolean updateByBo(MediaMpQrcodeLinkBo bo) {
        MediaMpQrcodeLink update = BeanUtil.toBean(bo, MediaMpQrcodeLink.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(MediaMpQrcodeLink entity){
        //TODO 做一些数据校验,如唯一约束
        LoginUser loginUser =  LoginHelper.getLoginUser();
        entity.setUserId(loginUser.getUserId());
        entity.setDeptId(loginUser.getDeptId());
        LambdaQueryWrapper<MediaMpQrcodeLink> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MediaMpQrcodeLink::getLink,entity.getLink());
        if(count(queryWrapper) >= 1){
            throw new RuntimeException("当前链接已被用户使用！");
        }
    }

    /**
     * 批量删除微信群二维码参数
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }



//
//
//    @Override
//    public List<String> checkQRCodeContent(MediaMpQrcodeLink mediaMpQrcodeLink) {
//        List<String> linkList = new ArrayList<>();
//        if(mediaMpQrcodeLink == null){
//            throw new RuntimeException("id不存在!");
//        }
//        String link = mediaMpQrcodeLink.getLink();
//        if(link.contains("b6d=")){
//            String domain = "";
//            try{
//                String regex = "<script>(.+?)var domain='(.+?)';(.+?)</script>";
//                Matcher b6dContent = Pattern.compile("b6d=([^&]+)").matcher(link);
//                Matcher matcher = Pattern.compile(regex, Pattern.DOTALL).matcher(Jsoup.connect(link).get().body().toString());
//                if (matcher.find() && b6dContent.find()) {
//                    String headValue = b6dContent.group(1);
//                    domain = matcher.group(2);
//                    String callback = "jsonp_" + WxUtils.getRandomNumber(17);
//                    String type = link.contains("i=6") ? "i=6" : link.contains("i=10") ? "i=10" : "";
//                    String url = domain + "/api/h5/detail?b6d=" + headValue +"&" + type +"&v=2.0&callback=" + callback;
//                    String htmlContent  =  douyinApi.getWechatData(url).getContent();
//                    if(XStringUtils.isEmpty(htmlContent)){
//                        throw new RuntimeException("获取内容失败！");
//                    }
//                    String response = htmlContent.substring(htmlContent.indexOf("('") + 2,htmlContent.indexOf("')")).replaceAll("975","");
//
//                    byte[] decodedBytes = Base64.getDecoder().decode(response);
//                    String decodedString = new String(decodedBytes);
//                    JSONObject jsonObject =  JSONObject.parseObject(decodedString);
//                    Document document = Jsoup.parse(jsonObject.getString("content"));
//                    Element element = document.body().select("script").get(3);
//                    String re = element.toString();
//                    String resData = re.substring(re.indexOf("content") + 11,re.indexOf("';")); //获取js里面的content数据
//                    try{
//                        String tempData =  WxUtils.deCodeBase64Data(resData); //解密
//                        String content = JSONObject.parseObject(tempData).getString("content");
//                        String imageJson = WxUtils.deCodeBase64Data(content.substring(1));
//                        Document imageDoc = Jsoup.parse(imageJson);
//                        String imageBase64 = imageDoc.select("img").attr("src");
//                        //如果当前解析的参数是链接则直接获取字节流
//                        if(!imageBase64.contains("http")){
//                            try {
//                                BASE64Decoder decoder = new BASE64Decoder();
//                                byte[] bt = decoder.decodeBuffer(imageBase64.substring(imageBase64.indexOf(",") + 1));
//                                //保存图片内容
//                                //saveImageQR(new ByteArrayInputStream(bt),String.valueOf(id));
//                            } catch (Exception e) {
//                                e.printStackTrace();
//                            }
//                        }else{
//                            linkList.add(imageBase64);
//                        }
//                    }catch (IOException e){
//                        e.printStackTrace();
//                    }
//                }
//            }catch (Exception e){
//                e.printStackTrace();
//            }
//        }else if(link.contains("lw=")){
//            try{
//                Pattern pattern = Pattern.compile("lw=([^&#]*)");
//                Matcher matcher = pattern.matcher(link);
//                if (matcher.find()) {
//                    String lwValue = matcher.group(1);
//                    String codeData = WxUtils.deCodeBase64Data(lwValue);
//                   String[] val =  codeData.split(",");
//                   String jpContent =  douyinApi.getWechatData("https://mycnyc.com/s/" + val[1] + "?fnname=jp_" + WxUtils.getRandomNumber(17)).getContent();
//                    Matcher jpBase = Pattern.compile("\\('(.*?)'\\)").matcher(jpContent);
//                    if (jpBase.find()) {
//                        String content = jpBase.group(1);
//                        String jsonImage = WxUtils.deCodeBase64Data(content.substring(1));
//                        Matcher jImage = Pattern.compile("decode\\(\\s*'([^']*)'\\s*\\)").matcher(jsonImage);
//                        if (jImage.find()) {
//                            String decodeContent = jImage.group(1);
//                            JSONObject data =  JSONObject.parseObject(WxUtils.deCodeBase64Data(decodeContent));
//                            String imageUrl =  Jsoup.parse(data.getString("articleInfo")).select("img").attr("src");
//
//                            linkList.add(imageUrl);
//                            String title =  data.getString("title");
//                        }
//                    }
//                }
//            }catch (Exception e){
//                e.printStackTrace();
//            }
//        }else if(link.contains("code=")){
//            Matcher matcher = Pattern.compile("code=([^&#]+)").matcher(link);
//            if (matcher.find()) {
//                String code = matcher.group(1);
//                String firstContent = douyinApi.getWechatData(link).getContent();
//                //获取头部链接
//                Matcher domainUrl = Pattern.compile("var url = '([^']+)'").matcher(firstContent);
//                if (domainUrl.find()) {
//                    String requestLink = domainUrl.group(1);
//                    String twoLink = requestLink + code + ".html";
//                    String resCon = douyinApi.getWechatData(twoLink).getContent();
//                    Matcher threeContent = Pattern.compile("var content = \"(.+?)\";").matcher(resCon);
//                    if (threeContent.find()) {
//                        String content = threeContent.group(1);
//                        try{
//                            String baseContent = WxUtils.deCodeBase64Data(content.substring(1));
//                            Matcher pageContent = Pattern.compile("window\\.pages=\"(.+?)\";").matcher(baseContent);
//                            if (pageContent.find()) {
//                                String pages = pageContent.group(1);
//                                String resData = WxUtils.deCodeBase64Data(pages.substring(1));  // extract pages content from first match
//                                JSONObject image = JSONObject.parseObject(resData);
//                                JSONObject data =  (JSONObject)image.getJSONArray("list").get(0);
//
//                                String imageLinkData = "https:" + data.getJSONObject("properties").getString("autothumbSrc");
//                                linkList.add(imageLinkData);
//                                JSONArray elementsList =  data.getJSONArray("elements");
//                                for(int i = 0 ; i <elementsList.size(); i ++ ){
//                                    JSONObject jsonData = (JSONObject)elementsList.get(i);
//                                    String src = jsonData.getJSONObject("properties").getString("src");
//                                    linkList.add(src);
//                                }
//                            }
//                        }catch (Exception e){
//                            e.printStackTrace();
//                        }
//                    }
//                }
//            }
//        }
//        mediaMpQrcodeLink.setImageUrl(linkList.get(0));
//        updateById(mediaMpQrcodeLink);
//        //保存图片内容到子表
//        try{
//            for(String imageLink : linkList){
//                saveImageQR(WxUtils.getImageInputStream(imageLink),String.valueOf(mediaMpQrcodeLink.getId()));
//            }
//        }catch (IOException e){
//            System.out.println("图片获取失败！");
//        }
//        return linkList;
//    }




    /**
     * 截取gif每一帧的图片并识别是否为二维码，如果是二维码则解析二维码内容并遍历到一个数组里面返回
     * @param gifFile gif格式的图片文件
     * @return 包含二维码内容的数组
     */
    public List<String> decodeQRCodeFromGif(InputStream gifFile) {
        List<String> qrCodeContents = new ArrayList<>();
        String imageType = "";
        try {
            ImageInputStream iis = ImageIO.createImageInputStream(gifFile);
            Iterator<ImageReader> imageReaders = ImageIO.getImageReaders(iis);
            ImageReader reader = null;
            if (imageReaders.hasNext()) {
                 reader = imageReaders.next();
                imageType = reader.getFormatName().toLowerCase();
            }
            reader.setInput(iis);
            if("gif".equals(imageType)){
                int numFrames = reader.getNumImages(true);
                for (int i = 0; i < numFrames; i++) {
                    BufferedImage frame = reader.read(i);
                    //   判断是否为二维码
                    String resContent = isQRCode(frame);
                    if (XStringUtils.isNotEmpty(resContent)) {
                        //   解析二维码内容
                        qrCodeContents.add(resContent);
                    }
                }
            }else{
                BufferedImage frame = reader.read(0); // 0 represents the index of the first frame in the image sequence.
                String resContent = isQRCode(frame);
                if (XStringUtils.isNotEmpty(resContent)) {
                    qrCodeContents.add(resContent);
                }
            }
            iis.close();
            reader.dispose();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return qrCodeContents;
    }




    public String saveImageQR(InputStream inputStream,String linkId) {
        StringBuilder msg = new StringBuilder();
        try{
            List<String> linkList = decodeQRCodeFromGif(inputStream);
            int noUse = 0;
            int useEd = 0;
            for(String item : linkList){
                MediaMpQrcodeDataBo mediaMpQrcodeData = new MediaMpQrcodeDataBo();
                mediaMpQrcodeData.setLink(item);
                mediaMpQrcodeData.setLinkId(linkId);
                mediaMpQrcodeData.setQrCodeUpdateTime(new Date());

                //查询是否包含重复链接
                LambdaQueryWrapper<MediaMpQrcodeData> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(MediaMpQrcodeData::getLink,item);
                MediaMpQrcodeData mediaMpQrcode = mediaMpQrcodeDataService.getOne(queryWrapper);
                if(mediaMpQrcode == null){
                    noUse ++ ;
                    mediaMpQrcodeDataService.insertByBo(mediaMpQrcodeData);
                }else{
                    useEd ++ ;
                }
            }
            msg.append("保存成功" + noUse + "个二维码！\r\n");
            if(useEd > 0){
                msg.append( useEd + "个二维码已被其他用户使用！");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return msg.toString();
    }


    /**
     * 判断图片是否为二维码
     * @param image 待判断的图片
     * @return 是否为二维码
     */
    private String isQRCode(BufferedImage image) {
         // TODO: 实现二维码识别算法
        // Use the ZXing library to create a BinaryBitmap from the BufferedImage
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(image)));
        // Set decoding hints to improve performance and accuracy
        Hashtable<DecodeHintType, Object> hints = new Hashtable<>();
        hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
        hints.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.allOf(BarcodeFormat.class));
        hints.put(DecodeHintType.CHARACTER_SET, StandardCharsets.UTF_8.name());
        // Use the ZXing library to decode the BinaryBitmap and return the result as a string
        try {
            Result result = new MultiFormatReader().decode(bitmap, hints);
            return result.getText();
        } catch (NotFoundException e) {
            // If no QR code is found in the image, return an empty string
            return "";
        }
    }






}
